package com.cqc.rxjava01.Http;

import android.support.annotation.NonNull;

import com.cqc.rxjava01.exception.HttpDataNullException;
import com.cqc.rxjava01.entity.CommonResult;
import com.cqc.rxjava01.entity.User;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

/**
 * Created by a on 2018/9/20.
 * 进一步封装
 * 不返回CommonResult<User>，只返回User
 */

public class UserApiWrapper {

    private static UserApiWrapper wrapper;
    private final UserApi userApi;

    private UserApiWrapper() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiConstant.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addConverterFactory(ScalarsConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        userApi = retrofit.create(UserApi.class);
    }

    public static UserApiWrapper getInstance() {
        if (wrapper == null)
            wrapper = new UserApiWrapper();
        return wrapper;
    }


    public Observable<User> login(User user) {
        Observable<CommonResult<User>> observable = userApi.login4(user).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
        return transform(observable);
    }

    public Observable<User> login2(User user) {
        Observable<CommonResult<User>> observable = userApi.login4(user).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
        return transform2(observable);
    }

    /**
     * 从老郭那看到的，泛型这么使用没看懂。使用了两种泛型。
     * flatMap换成concatMap也可以
     *
     * @param observable
     * @param <R>
     * @param <T>
     * @return
     */
    private <R extends CommonResult<T>, T> Observable<T> transform(@NonNull Observable<R> observable) {
        return observable.flatMap(new Function<R, ObservableSource<T>>() {
            @Override
            public ObservableSource<T> apply(final R r) throws Exception {
                return Observable.create(new ObservableOnSubscribe<T>() {
                    @Override
                    public void subscribe(ObservableEmitter<T> emitter) throws Exception {
                        if (r.data == null) {
                            emitter.onError(new HttpDataNullException("httpResp data is null."));
                            return;
                        }
                        emitter.onNext(r.data);
                    }
                });
            }
        });
    }

    //-------------------------------------------------------------------------------------------------
    /**
     * response:去掉msg  success  只保留data并返回。使用了一种泛型
     * flatMap()转换数据类型
     * flatMap换成concatMap也可以
     *
     * @param observable
     * @param <T>
     * @return
     */
    private <T> Observable<T> transform2(@NonNull Observable<CommonResult<T>> observable) {
        return observable.flatMap(new Function<CommonResult<T>, ObservableSource<T>>() {
            @Override
            public ObservableSource<T> apply(final CommonResult<T> result) throws Exception {
                return Observable.create(new ObservableOnSubscribe<T>() {
                    @Override
                    public void subscribe(ObservableEmitter<T> e) throws Exception {
                        if (result.getData() == null) {
                            e.onError(new HttpDataNullException("httpResp data is null."));
                            return;
                        }
                        e.onNext(result.getData());
                    }
                });
            }
        });
    }

}
